#include <algorithm>
#include "rs_affix.h"


void rs_affix::rs_affix_init (
        const rs_string& affix_cg_fname,
        const rs_string& og_base_name)
{
    if (rsa_initialized)
        return;
    // initializes affixes; most of data are read from file
    init_affix_cg (affix_cg_fname);
    rsa_valid = true;
    rsa_name = og_base_name;
    rsa_alphabet = L"";
    rs_string affix_fname = get_rules_fname ();
    init_mc_affixes(); // todo: make mc_affixes specific for each ography, to be read from file
    rsa_valid = parse_affixes(affix_fname, rsg_afcom, rsg_afgroup);
    rsa_initialized = true;
}


rs_string rs_affix::get_rules_fname (const rs_string& abbreviation)
{
    return abbreviation + L"_rules.rst";
}


rs_string rs_affix::get_rules_fname () const
{
    return get_rules_fname (rsa_name);
}


bool afreal::split_or_apply (
    const rs_string& word,
    rs_string& modified,
    bool do_split) const
{
    // tries to split or apply affix to 'word'
    // if conditions are met, generates the 'modified' and returns true
    // if conditions are not met, returns false
    // affix is either prefix or suffix, as stored in afr_re.is_suffix()
    const rs_string& search  = do_split? afr_add : afr_sub;
    const rs_string& replace = do_split? afr_sub : afr_add;
    int pos = static_cast<int> (word.length()) - static_cast<int> (search.length());
    if (pos <= 0)
        return false;   // searched affix is not shorter than word
    if (afr_flags & af_suffix) { // suffix
        bool found = word.substr(pos) == search;
        if (!found)
            return false;   // not found such affix
        modified = word.substr(0, pos);
        if (!afr_re.matches (modified))
            return false;
        modified += replace;
    } else { // prefix
        bool found = word.substr(0, search.length()) == search;
        if (!found)
            return false;   // not found such affix
        modified = word.substr(search.length());
        if (!afr_re.matches (modified))
            return false;
        modified = replace + modified;
    }
    return true;
}


afreal::operator rs_string () const
{
    rs_string afrp_str (afr_re);
    if (afr_flags & af_suffix) {
        return afr_re.get_str()
            + L"/" + afr_sub
            + L"/" + afr_add
            //+ L"; cond=" + afrp_str // no need to check it, seems to work well
            ;
    } else {
        return 
            afr_add
            + L"/" + afr_sub
            + L"/" + afr_re.get_str()
            //+ L"; cond=" + afrp_str // no need to check it, seems to work well
            ;
    }
}


typedef pair <unsigned, unsigned> uint_pair;  // first: index in rsa_afreal; second: length of string

bool uint_pair_cmp_second_decr (const uint_pair &a, const uint_pair &b)
{
    // when the 'sort' is called on such types, vector is sorted by .second, in decreasing order
    return a.second > b.second;
}

static flag_text line_type_ft[]={
    af_prefix, L"prefix",
    af_suffix, L"suffix",
    af_afreal, L"afreal",
    af_alphabet, L"alphabet",
    0, 0
};

static flag_text affix_ft[]={
    af_duplicates, L"dupl",
    af_deletes_e, L"e_del",
    af_changes_y, L"y_chan",
    0, 0
};

void rs_affix::add_affix_realization (
    const rs_string& affix_text,
    unsigned affix_flags,
    unsigned affix_rix,
    unsigned affix_acix,
    bool is_default)
{
    // parses the string representation 'affix_text' together with 'affix_flags'
    // and appends affix to either rsa_mc_afreal or rsa_affix
    rs_string_v afreal_fields;
    string_to_vec_delim (affix_text, afreal_fields, L'/');
    if (afreal_fields.size()<3)
        afreal_fields.resize(3);
    rs_string cond, sub, add;
    if (affix_flags & af_suffix) {
        cond = afreal_fields[0];
        sub = afreal_fields[1];
        add = afreal_fields[2];
    } else {
        cond = afreal_fields[2];
        sub = afreal_fields[1];
        add = afreal_fields[0];
    }
    if (!is_lower(add) || !is_lower(sub)) {
        rs_report_error (L"afreal has non-lowercase characters in "
            + add + L"/" + sub);
        return;
    }
    bool is_start, is_end; // used only to store info from strip_regex_start_end
    strip_regex_start_end (cond, is_start, is_end);
    afreal afr (add, sub, cond, affix_flags, affix_acix);
    if (!afr.is_valid()) {
        return;
    }
    if (is_default) {
        rsa_mc_afreal.push_back (afr);
    } else {
        rsa_afreal.push_back (afr);
        unsigned afreal_rix = unsigned (rsa_afreal.size()) - 1;
        // now update rsa_affix[affix_rix]
        if (rsa_affix[affix_rix].get_first() == 0) {
            rsa_affix[affix_rix].set_first (afreal_rix);
        }
        rsa_affix[affix_rix].set_size (
            (afreal_rix - rsa_affix[affix_rix].get_first() + 1));
    }
}


void rs_affix::init_mc_affixes()
{
    // todo read mc_affixes from file
    rs_string clean_name;
    unsigned affix_rix=0;
    unsigned affix_acix=0;
    add_affix_realization (L"[^aeiou][aeiou]/p/pp" + clean_name, af_suffix | af_duplicates, affix_rix, affix_acix, true);
    add_affix_realization (L"[^aeiou][aeiou]/t/tt" + clean_name, af_suffix | af_duplicates, affix_rix, affix_acix, true);
    add_affix_realization (L"[^aeiou][aeiou]/k/kk" + clean_name, af_suffix | af_duplicates, affix_rix, affix_acix, true);
    add_affix_realization (L"[^aeiou][aeiou]/b/bb" + clean_name, af_suffix | af_duplicates, affix_rix, affix_acix, true);
    add_affix_realization (L"[^aeiou][aeiou]/d/dd" + clean_name, af_suffix | af_duplicates, affix_rix, affix_acix, true);
    add_affix_realization (L"[^aeiou][aeiou]/g/gg" + clean_name, af_suffix | af_duplicates, affix_rix, affix_acix, true);
    add_affix_realization (L"[^aeiou][aeiou]/n/nn" + clean_name, af_suffix | af_duplicates, affix_rix, affix_acix, true);
    add_affix_realization (L"[^aeiou][aeiou]/m/mm" + clean_name, af_suffix | af_duplicates, affix_rix, affix_acix, true);
    add_affix_realization (L"[^aeiou][aeiou]/r/rr" + clean_name, af_suffix | af_duplicates, affix_rix, affix_acix, true);
    add_affix_realization (L"[^aeiou][aeiou]/v/vv" + clean_name, af_suffix | af_duplicates, affix_rix, affix_acix, true);
    add_affix_realization (L"[aeiou][^aeiou]/e/" + clean_name, af_suffix | af_deletes_e, affix_rix, affix_acix, true);
    // todo: check the next af_deletes_e morfem change
    add_affix_realization (L"[^aeiou]g/e/" + clean_name, af_suffix | af_deletes_e, affix_rix, affix_acix, true);
    add_affix_realization (L"/y/i" + clean_name, af_suffix | af_changes_y, affix_rix, affix_acix, true);
    add_affix_realization (L"//" + clean_name, af_suffix, affix_rix, affix_acix, true);
    add_affix_realization (L"//" + clean_name, af_prefix, affix_rix, affix_acix, true);
}


bool rs_affix::parse_affixes(
    const rs_string& affix_fname,
    const vector<affix_cg>& afcom,
    const vector<affix_cg>& afgroup)
{
    // returns false if major error occurs while parsing
    rs_log_file (L"Parsing affix table: " + affix_fname);
    rs_table rst_affix (affix_fname, false);
    if (!rst_affix.is_valid()) {
        rs_report_error (L"Missing affix table: ", affix_fname);
        return false;
    }
    if (rst_affix.get_col_type (any_cix(0)) != rt_text2  ||
        rst_affix.get_col_type (any_cix(1)) != rt_text2  ||
        rst_affix.get_col_type (any_cix(2)) != rt_text2) {
        rs_report_error (L"Incorrect column types in affix table: ", affix_fname);
        return false;
    }
    // index [0] will be used for returning absent values
    rsa_affix.push_back(affix(0, 0, rs_rix::begin(),L""));
    // index [0] will be used for returning absent values
    rsa_afreal.push_back(afreal(L"(none)",L"(none)",L"",0,0));
    unsigned affix_flags=0;
    rs_string affix_name; // e.g. L"-ed" or L"un-", as in afcom
    unsigned affix_acix=0;   // index of affix_name in afcom
    unsigned affix_rix=0;   // index of affix in rsa_affix
    bool expecting_affix = true;
    for (rs_rix rix=rs_rix::begin(); rix<rst_affix.get_row_count(); rix++) {
        rs_string col0_text (rst_affix.get_text (text_cix(0), rix));
        rs_string col1_text (rst_affix.get_text (text_cix(1), rix));
        rs_string col2_text (rst_affix.get_text (text_cix(2), rix));
        if (col0_text.size() == 0)
            continue; // empty line
        rs_string affix_name;
        unsigned line_type;
        // every non-line has in col0 type of row that is parsed here
        if (!parse_item (col0_text, affix_name, line_type, line_type_ft, 
            L"line type"))
            continue;
        if (line_type & af_alphabet) {
            // alphabet as used in dictionary
            rsa_alphabet = col1_text;
            continue;
        }
        if (line_type & (af_prefix | af_suffix)) {
            if (!string_to_flags (col1_text, affix_flags, affix_ft, L"affix")) {
                // error already reported
                expecting_affix = true;
                continue;
            }
            affix_flags |= line_type;
            if ((affix_flags & af_prefix)  &&
                (affix_flags & (af_duplicates | af_deletes_e | af_changes_y))) {
                rs_report_error (L"prefix can't be combined with other flags",
                    L" in flags : " + col0_text);
                expecting_affix = true;
                continue;
            }
            affix_acix=0;
            for (unsigned acix=0; acix<afcom.size(); acix++) {
                if (afcom[acix].get_name() == affix_name) {
                    affix_acix = acix;
                    break;
                }
            }
            if (affix_acix == 0) {
                rs_report_error (L"Unknown affix (not listed among common affixes): ", affix_name);
                expecting_affix = true;
                continue;
            }
            affix new_affix (affix_acix, affix_flags, rix, col2_text);
            rsa_affix.push_back (new_affix);
            affix_rix = unsigned (rsa_affix.size()) - 1;
            
            rs_string clean_name;
            // clean_name is either affix_name without "-" or first part of col2_text
            clean_name = nth_substring (col2_text, 0, L"|");
            if (clean_name == L"") {
                clean_name = affix_name;
                if (affix_flags & af_suffix) {
                    if (clean_name.substr(0,1) == L"-")
                        clean_name = clean_name.substr (1);
                    else {
                        rs_report_error (
                            L"affix name doesn't suit flag, flag 'suffix' requires initial '-' in affix name: ",
                            affix_name);
                        expecting_affix = true;
                        continue;
                    }
                } else {
                    if (clean_name.substr(clean_name.length()-1) == L"-")
                        clean_name = clean_name.substr (0, clean_name.length()-1);
                    else {
                        rs_report_error (
                            L"affix name doesn't suit flag, flag 'prefix' requires final '-' in affix name: ",
                            affix_name);
                        expecting_affix = true;
                        continue;
                    }
                }
            }
            rsa_affix[affix_rix].set_clean_name (clean_name);
            expecting_affix = false;

            // add common morfem changing affix realizations
            for (size_t mcix=0;  mcix<rsa_mc_afreal.size();  mcix++) {
                unsigned mc_flags = rsa_mc_afreal[mcix].get_flags();
                if ((affix_flags & mc_flags) == mc_flags) {
                    rs_string afr_text (rsa_mc_afreal[mcix]);
                    if (affix_flags & af_suffix)
                        add_affix_realization (afr_text + clean_name, affix_flags, affix_rix, affix_acix);
                    else
                        add_affix_realization (clean_name + afr_text, affix_flags, affix_rix, affix_acix);
                }
            }
            continue; // no more processing for affix
        }
        if (expecting_affix) {
            rs_report_error (L"here are data for affix realization when expected data for affix itself: ",
                col0_text + L" " + col1_text + L" " + col2_text);
            continue;
        }
        // new affix realization
        add_affix_realization (col1_text, affix_flags, affix_rix, affix_acix);
    }
    // now follows initializiation of rsa_by_com
    rsa_by_com.resize (afcom.size());
    for (unsigned aix=1; aix<rsa_affix.size(); aix++) {
        rsa_by_com [rsa_affix[aix].get_acix()] = aix;
    }
    // now follows checking that all affixes are present
    bool all_affixes(true);
    for (unsigned acix=1; acix<rsa_by_com.size(); acix++) {
        if (rsa_by_com[acix] == 0) {
            rs_report_error (L"Missing affix in orthography: ",
                L"affix=" + afcom[acix].get_name()
                +L", orthography_table="+affix_fname);
            all_affixes=false;
        }
    }
    if (!all_affixes) {
        return false;
    }
    // now follows creation of indexes for splitting affixes
    // values at zero positions are for returning absent values
    rsa_sg_order.push_back(0);
    rsa_sg_start.push_back(0);
    rsa_sg_size.push_back(0);
    rsa_sg_order.reserve (afcom.size());
    rsa_sg_start.resize (afgroup.size());
    rsa_sg_size.resize (afgroup.size());
    for (unsigned agix=1; agix < afgroup.size(); agix++) {
        rsa_sg_start[agix] = unsigned (rsa_sg_order.size());
        vector<uint_pair> afis; // afreal index and size
        for (unsigned afrix=1; afrix<rsa_afreal.size(); afrix++) {
            unsigned afcix = rsa_afreal[afrix].get_acix();
            unsigned afgix = afcom[afcix].get_prio();
            if (agix == afgix)
                afis.push_back (uint_pair (afrix, rsa_afreal[afrix].get_split_len()));
        }
        sort (afis.begin(), afis.end(), uint_pair_cmp_second_decr);
        for (unsigned i=0; i<afis.size(); i++) {
            rsa_sg_order.push_back (afis[i].first);
        }
        rsa_sg_size [agix] = unsigned (rsa_sg_order.size()) - rsa_sg_start[agix];
    }
    // now follows creation of indexes for applying affixes
    for (size_t aix=1; aix<rsa_affix.size(); aix++) {
        affix* afp=&rsa_affix[aix];
        size_t first = afp->get_first();
        size_t size = afp->get_size();
        vector<unsigned> afr_index_vec;
        get_sorted_afreal_indexes (first, size, afr_index_vec);
        afp->set_afreal_indexes  (afr_index_vec);
    }


    rs_log_file (L"affix initialization for orthography " + rsa_name + L" done, now follows parsed output");
    // test output
    //for (size_t aix=1; aix<rsa_affix.size(); aix++) {
    //    affix* afp=&rsa_affix[aix];
    //    rs_log_file (L"affix "+rs_stringed (aix)+L": " 
    //        + afcom[rsa_affix[aix].get_acix()].get_name()
    //        + L"/" + rsa_affix[aix].get_clean_name()
    //        + L" affix realizations:");
    //    size_t first = afp->get_first();
    //    size_t size = afp->get_size();
    //    for (size_t arix=first; arix<first+size; arix++) {
    //        rs_log_file (L"afreal " + rs_stringed(arix) + L": " + 
    //            rs_string (rsa_afreal [arix]));
    //    }
    //    rs_log_file (L"affix realization indexes, sorted by decreasing length of 'sub' expression");
    //    const vector<unsigned>& afr_index_vec = afp->get_afreal_index_vec ();
    //    for (size_t arix=0; arix<size; arix++) {
    //        rs_log_file (L"afreal index " + rs_stringed(arix) + L": " + 
    //            rs_stringed (afr_index_vec [arix]));
    //    }
    //}
    //rs_log_file (L"all affix realizations by groups and size, used when splitting affixes:");
    //for (unsigned agix=1; agix < afgroup.size(); agix++) {
    //    rs_log_file (L"group " + rs_stringed (agix) +L": "
    //        +afgroup[agix].get_name());
    //    for (unsigned arix=rsa_sg_start[agix]; arix<rsa_sg_start[agix]+rsa_sg_size[agix]; arix++) {
    //        rs_log_file (L"afreal " + rs_stringed(arix) + L": " + 
    //            rs_string (rsa_afreal [rsa_sg_order[arix]]));
    //    }
    //}
    return true;   
}


bool name_present_cg (const vector<affix_cg>& cg, const rs_string& name)
{  // returns true if case-insensitive search within 'cg' finds 'name'
    vector<affix_cg>::const_iterator it;
    for (it=cg.begin(); it!=cg.end(); it++) {
        if (upper_case (it->get_name()) == upper_case(name))
            return true;
    }
    return false;
}


void rs_affix::get_sorted_afreal_indexes (unsigned start_ix, unsigned size, vector<unsigned>& afr_index_vec)
{
    vector<pair<unsigned, unsigned> > ix_len_vec;
    unsigned i;
    for (i=start_ix; i<start_ix+size; i++) {
        pair<unsigned, unsigned> ix_len;
        ix_len.first = i;
        ix_len.second = rsa_afreal[i].get_sub_len();
        ix_len_vec.push_back (ix_len);
    }
    stable_sort (ix_len_vec.begin(), ix_len_vec.end(), uint_pair_cmp_second_decr);
    afr_index_vec.clear();
    for (i=0; i<size; i++) {
        afr_index_vec.push_back (ix_len_vec[i].first);
    }
}


unsigned rs_affix::get_affix_ix (const rs_string& affix_cg_name) const
{
    unsigned i, aff_size = rsg_afcom.size();
    for (i=0; i<aff_size; i++) {
        if (rsg_afcom[i].get_name() == affix_cg_name)
            return i;
    }
    return 0;
}


rs_string rs_affix::show_affixes (
    const rs_string& affixed,
    const rs_string& stem,
    const vector<size_t>& af_vec) const
{
    // converts decomposition to textual form
    rs_string result (stem);
    vector<size_t>::const_reverse_iterator afvit;
    for (afvit=af_vec.rbegin(); afvit != af_vec.rend(); afvit++) {
        unsigned acix = *afvit;
        result+=L","+rsg_afcom[acix].get_name();
    }
    return result;
}


bool rs_affix::split_affixes (
    const rs_string& affixed,
    rs_string& stem,
    vector<size_t>& af_vec,
    //unsigned atix__, // affix table index
    const rs_column& text_column,
    unsigned min_stem_len,
    unsigned max_level) const
{ // decomposes 'affixed' into stem and vector of affixes af_vec
    // dict_cix is column in dictionary to be used for searching word forms
    // e.g. "unknowingly" -> "know,-ing,-ly,un-"
    // works only for words that consist entirely of lower-case ascii characters
    // returns true if split succedeed given the constaints
    // returns false otherwise
    rs_rix rix;
    unsigned min_level = 1;
    bool several;
    rs_string word (affixed);
    bool found;
    bool in_lexicon;
    const rs_affix& rsa = *this; //rsg_affix[atix];
    af_vec.clear();
    stem = word;
    unsigned agix = 1;  // index to rsg_afgroup
    while (true) {
        if (max_level>0 && af_vec.size() >= max_level)
            return true;
        found = false;
        unsigned sg_start = rsa.get_sg_start (agix);
        unsigned sg_size = rsa.get_sg_size (agix);
        unsigned sg_end = sg_start + sg_size;
        for (unsigned arix=sg_start; arix<sg_end; arix++) {
            // todo: search faster for applicable suffixes, create state machine from all regex-es
            const afreal& af = rsa.get_afreal_to_split (arix);
            rs_string stem_try;
            if (!af.split (word, stem_try))
                continue;
            if (stem_try.length() < min_stem_len)
                continue;
            unsigned s1, s2;
            if (count_syllables (stem_try, s1, s2) < 1)
                continue;
            // todo: specify for every affix its own minimal number of syllables in stem 
            rix = text_column.get_text_row_any (stem_try, several);

            in_lexicon = rix.is_valid();
            if (!in_lexicon)
                continue;
            af_vec.push_back (af.get_acix());
            word = stem = stem_try;
            found = true;
            break;
        }
        if (!found)
            agix++;
        else if ((rsg_afgroup [agix].get_flags() & af_repeatable) == 0)
            agix++;
        if (agix >= rsa_sg_start.size()) {
            if (min_level==0 || af_vec.size()>=min_level)
                return true;
            break;
        }
    }
    return false;
}


bool rs_affix::apply_affixes (
    rs_string& composed_word,
    const rs_string& stem,
    const vector<size_t>& af_vec) const
{
    // Composes affixes af_vec to 'stem' and records the result as 'composed_word'
    bool result;
    rs_string word(stem), affixed;
    const rs_affix& rsa = *this; //rsg_affix[atix];
    vector<size_t>::const_reverse_iterator afvit;
    for (afvit=af_vec.rbegin(); afvit != af_vec.rend(); afvit++) {
        unsigned acix = *afvit;
        const affix* afp=&rsa.get_affix_to_apply (acix);
        result=false;
        unsigned first = afp->get_first();
        unsigned size = afp->get_size();
        const vector<unsigned>& afr_index_vec = afp->get_afreal_index_vec ();
        for (unsigned arix=0; arix<size; arix++) {
            const afreal* afrp=&rsa.get_afreal (afr_index_vec[arix]);
            result = afrp->apply (word, affixed);
            if (result) {
                word = affixed;
                break;
            }
        }
        if (!result)
            // no affix realization for this affix
            return false;
    }
    composed_word = word;
    return true;
}


static flag_text affix_cg_type_ft[]={
    // types of lines
    af_group, L"group",
    af_prefix, L"prefix",
    af_suffix, L"suffix",
    0, 0
};
static flag_text affix_group_ft[]={
    af_prefix, L"prefix",
    af_suffix, L"suffix",
    af_repeatable, L"repeatable",
    0, 0
};



bool rs_affix::init_affix_cg(const rs_string& affix_cg_fname)
{
    // initializes vectors rsg_afcom and rsg_afgroup with data from table
    rs_log_file (L"checking and converting affix groups and common data from table "+affix_cg_fname);
    rs_table rst_affix_cg (affix_cg_fname, false);
    if (!rst_affix_cg.is_valid()) {
        rs_report_error (L"missing affix groups and common table: ", affix_cg_fname);
        return false;
    }
    if (rst_affix_cg.get_col_type (any_cix(0)) != rt_text2  ||
        rst_affix_cg.get_col_type (any_cix(1)) != rt_text2) {
        rs_report_error (L"Incorrect column types in affix groups and common table: ", affix_cg_fname);
        return false;
    }
    // indexes [0] will be used for returning absent values
    rsg_afcom.push_back(affix_cg(L"(none)",0,0));
    rsg_afgroup.push_back(affix_cg(L"(none)",0,0));

    unsigned group_flags=0;//, prev_flags=0;
    rs_string affix_cg_name; // e.g. L"-ed" or L"un-" or "inflection"
    unsigned affix_acix=0;   // index of affix_cg_name in afcom
    unsigned affix_rix=0;   // index of affix in rsa_affix
    unsigned afreal_rix=0;
    bool expecting_group = true;
    unsigned priority=0;
    for (rs_rix rix=rs_rix::begin(); rix<rst_affix_cg.get_row_count(); rix++) {
        rs_string col0_text (rst_affix_cg.get_text (text_cix(0), rix));
        rs_string col1_text (rst_affix_cg.get_text (text_cix(1), rix));
        // every line is either 
        // - empty
        // - has data on affix group (col0_text starts with '+')
        // - has data on affix common (col0_text is ':')
        if (col0_text.size() == 0)
            continue; // empty line
        unsigned cg_type;
        if (!parse_item (col0_text, affix_cg_name, cg_type, affix_cg_type_ft, 
            L"affix group or common type"))
            continue;
        if (expecting_group  &&  cg_type != af_group) {
            rs_report_error (L"expected affix group data: ", col0_text);
            continue;
        }
        if (cg_type == af_group) {
            if (!string_to_flags (col1_text, group_flags, affix_group_ft,
                L"affix group flags")) {
                    continue;
            }
        } else if ((cg_type & group_flags) == 0) {
            rs_report_error (L"affix type different than specified for group: ");
            continue;
        }
        expecting_group = false;
        if (cg_type == af_group) {
            if (name_present_cg (rsg_afgroup, affix_cg_name)) {
                rs_report_error (L"Group already entered: ", affix_cg_name);
                continue;
            }
            priority = unsigned (rsg_afgroup.size());
            rsg_afgroup.push_back (affix_cg (affix_cg_name, cg_type|group_flags, priority));
        } else {
            if (name_present_cg (rsg_afcom, affix_cg_name)) {
                rs_report_error (L"Affix already entered: ", affix_cg_name);
                continue;
            }
            rsg_afcom.push_back (affix_cg (affix_cg_name, cg_type|group_flags, priority));
        }
    }

    // test output
    //for (size_t acix=1; acix<rsg_afgroup.size(); acix++) {
    //    affix_cg* acgp=&rsg_afgroup[acix];
    //    rs_log_file (L"affix group "+rs_stringed (acix)+L": " + acgp->get_name()
    //        + L", priority=" + rs_stringed (acgp->get_prio())
    //        + L", flags=" + flags_to_string (acgp->get_flags(), affix_group_ft));
    //    for (size_t afix=1; afix<rsg_afcom.size(); afix++) {
    //        if (rsg_afcom[afix].get_prio() == acgp->get_prio()) {
    //            rs_log_file (L"affix common: " + rs_stringed(afix)
    //                + L": " + rsg_afcom[afix].get_name()
    //                + L", priority=" + rs_stringed (rsg_afcom[afix].get_prio())
    //                + L", flags=" + flags_to_string (rsg_afcom[afix].get_flags(), affix_group_ft));
    //        }
    //    }
    //}
    return true;   
}


